<!DOCTYPE html>
<html>
<head>
    <title>Electromagnetism Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="400" height="500"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Helper functions for drawing arrows ---

        /**
         * Draws an arrow from (x1, y1) to (x2, y2).
         * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
         * @param {number} x1 - The starting x-coordinate.
         * @param {number} y1 - The starting y-coordinate.
         * @param {number} x2 - The ending x-coordinate.
         * @param {number} y2 - The ending y-coordinate.
         */
        function drawArrow(ctx, x1, y1, x2, y2) {
            const headlen = 10;
            const angle = Math.atan2(y2 - y1, x2 - x1);
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.lineTo(x2 - headlen * Math.cos(angle - Math.PI / 6), y2 - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(x2, y2);
            ctx.lineTo(x2 - headlen * Math.cos(angle + Math.PI / 6), y2 - headlen * Math.sin(angle + Math.PI / 6));
            ctx.stroke();
        }

        /**
         * Draws a double-headed arrow between two points.
         * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
         * @param {number} x1 - The starting x-coordinate.
         * @param {number} y1 - The starting y-coordinate.
         * @param {number} x2 - The ending x-coordinate.
         * @param {number} y2 - The ending y-coordinate.
         */
        function drawDoubleArrow(ctx, x1, y1, x2, y2) {
            const headlen = 8;
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);

            // Arrowhead at (x2, y2)
            let angle = Math.atan2(y2 - y1, x2 - x1);
            ctx.moveTo(x2, y2);
            ctx.lineTo(x2 - headlen * Math.cos(angle - Math.PI / 6), y2 - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(x2, y2);
            ctx.lineTo(x2 - headlen * Math.cos(angle + Math.PI / 6), y2 - headlen * Math.sin(angle + Math.PI / 6));

            // Arrowhead at (x1, y1)
            angle = Math.atan2(y1 - y2, x1 - x2);
            ctx.moveTo(x1, y1);
            ctx.lineTo(x1 - headlen * Math.cos(angle - Math.PI / 6), y1 - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(x1, y1);
            ctx.lineTo(x1 - headlen * Math.cos(angle + Math.PI / 6), y1 - headlen * Math.sin(angle + Math.PI / 6));
            
            ctx.stroke();
        }


        // --- Drawing parameters ---
        const centerX = 200;
        const topY = 100;
        const cylinderRadius = 90;
        const ellipseRatioY = 0.3;
        const cylinderHeight = 250;
        const bottomY = topY + cylinderHeight;

        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.font = '20px serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // --- 1. Draw Central Axis ---
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        ctx.moveTo(centerX, topY - 50);
        ctx.lineTo(centerX, bottomY + 20);
        ctx.stroke();
        ctx.setLineDash([]); // Reset to solid line

        // --- 2. Draw Cylinder Body ---
        // Top ellipse
        ctx.beginPath();
        ctx.ellipse(centerX, topY, cylinderRadius, cylinderRadius * ellipseRatioY, 0, 0, 2 * Math.PI);
        ctx.stroke();
        
        // Vertical sides and bottom arc
        ctx.beginPath();
        ctx.moveTo(centerX - cylinderRadius, topY);
        ctx.lineTo(centerX - cylinderRadius, bottomY);
        ctx.ellipse(centerX, bottomY, cylinderRadius, cylinderRadius * ellipseRatioY, 0, Math.PI, 2 * Math.PI);
        ctx.lineTo(centerX + cylinderRadius, topY);
        ctx.stroke();


        // --- 3. Draw Radius Arrow (R) ---
        ctx.font = 'italic 22px serif';
        drawArrow(ctx, centerX, topY, centerX + cylinderRadius, topY);
        ctx.fillText('R', centerX + cylinderRadius / 2, topY - 15);
        
        // --- 4. Draw Current Arrow (I) ---
        const currentArrowX = centerX - cylinderRadius * 0.6;
        const currentArrowCenterY = topY + cylinderHeight / 2;
        drawArrow(ctx, currentArrowX, currentArrowCenterY + 40, currentArrowX, currentArrowCenterY - 40);
        ctx.fillText('I', currentArrowX - 20, currentArrowCenterY);

        // --- 5. Draw Shaded Rectangle and label (l) ---
        const rectTopY = topY + 90;
        const rectHeight = 80;
        const rectWidth = cylinderRadius * 0.7;
        const rectBottomY = rectTopY + rectHeight;
        
        // Rectangle outline
        ctx.beginPath();
        ctx.rect(centerX, rectTopY, rectWidth, rectBottomY - rectTopY);
        ctx.stroke();
        
        // Shading lines (using clip)
        ctx.save();
        ctx.beginPath();
        ctx.rect(centerX, rectTopY, rectWidth, rectHeight);
        ctx.clip(); // Restrict drawing to inside the rectangle
        
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        // Draw diagonal lines from top-right to bottom-left
        for (let c = centerX + rectTopY; c < centerX + rectWidth + rectBottomY; c += 8) {
             const x1 = c - rectTopY;
             const y1 = rectTopY;
             const x2 = c - rectBottomY;
             const y2 = rectBottomY;
             ctx.moveTo(x1, y1);
             ctx.lineTo(x2, y2);
        }
        ctx.stroke();
        ctx.restore(); // Remove clipping region

        // 'l' dimension lines
        ctx.lineWidth = 2;
        const l_label_x = centerX + rectWidth + 30;
        
        // Dashed extension lines
        ctx.setLineDash([3, 3]);
        ctx.beginPath();
        ctx.moveTo(centerX + rectWidth, rectTopY);
        ctx.lineTo(l_label_x, rectTopY);
        ctx.moveTo(centerX + rectWidth, rectBottomY);
        ctx.lineTo(l_label_x, rectBottomY);
        ctx.stroke();
        ctx.setLineDash([]);
        
        // Double arrow and label
        drawDoubleArrow(ctx, l_label_x, rectBottomY, l_label_x, rectTopY);
        ctx.fillText('l', l_label_x + 15, rectTopY + rectHeight / 2);

        // --- 6. Draw Caption ---
        ctx.font = '20px KaiTi, STKaiti, serif';
        ctx.fillText('题 4 图', centerX, bottomY + 50);

    </script>
</body>
</html>